"""
Folder Model
文件夹模型 - 层级文件夹结构和路径管理
"""

import uuid
from enum import Enum

from sqlalchemy import Column, String, DateTime, Integer, Boolean, Text, ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship, backref

from ..core.database import Base


class FolderType(str, Enum):
    """文件夹类型枚举"""
    SYSTEM = "system"      # 系统文件夹
    USER = "user"         # 用户文件夹
    SHARED = "shared"     # 共享文件夹
    ARCHIVE = "archive"   # 归档文件夹
    TRASH = "trash"       # 回收站


class FolderVisibility(str, Enum):
    """文件夹可见性枚举"""
    PRIVATE = "private"    # 私有
    PUBLIC = "public"     # 公开
    SHARED = "shared"     # 共享


class Folder(Base):
    """文件夹模型"""

    __tablename__ = "folders"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    user_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("users.id", ondelete="CASCADE"), 
        nullable=False,
        index=True
    )
    
    # 层级结构
    parent_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("folders.id", ondelete="CASCADE"), 
        nullable=True,
        index=True
    )
    
    # 基本信息
    name = Column(String(100), nullable=False)
    description = Column(Text, nullable=True)
    folder_type = Column(String(20), nullable=False, default="user", index=True)
    
    # 路径信息
    path = Column(String(1000), nullable=False, index=True)  # 完整路径缓存
    level = Column(Integer, default=0)  # 层级深度
    
    # 统计信息
    content_count = Column(Integer, default=0)  # 直接内容数量
    total_content_count = Column(Integer, default=0)  # 包含子文件夹的总数量
    subfolder_count = Column(Integer, default=0)  # 子文件夹数量
    
    # 设置
    color = Column(String(7), nullable=True)  # 文件夹颜色 (#RRGGBB)
    icon = Column(String(50), nullable=True)  # 图标标识
    sort_order = Column(Integer, default=0)  # 排序顺序
    
    # 可见性和权限
    visibility = Column(String(20), nullable=False, default="private")
    is_system = Column(Boolean, default=False)  # 是否为系统文件夹
    is_locked = Column(Boolean, default=False)  # 是否锁定（防止删除）
    
    # 状态
    is_archived = Column(Boolean, default=False)
    is_deleted = Column(Boolean, default=False, index=True)
    
    # 时间戳
    created_at = Column(DateTime, default=func.now())
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    last_accessed_at = Column(DateTime, nullable=True)
    archived_at = Column(DateTime, nullable=True)
    deleted_at = Column(DateTime, nullable=True)

    # 关系
    user = relationship("User", back_populates="folders")
    parent = relationship("Folder", remote_side=[id], backref="children")
    contents = relationship("GeneratedContent", back_populates="folder", cascade="all, delete-orphan")

    def __repr__(self):
        return f"<Folder(id={self.id}, name={self.name}, path={self.path})>"

    @property
    def is_root(self) -> bool:
        """是否为根文件夹"""
        return self.parent_id is None

    @property
    def is_system_folder(self) -> bool:
        """是否为系统文件夹"""
        return self.is_system or self.folder_type == FolderType.SYSTEM

    @property
    def is_user_folder(self) -> bool:
        """是否为用户文件夹"""
        return self.folder_type == FolderType.USER

    @property
    def is_shared(self) -> bool:
        """是否为共享文件夹"""
        return self.visibility == FolderVisibility.SHARED

    @property
    def is_public(self) -> bool:
        """是否为公开文件夹"""
        return self.visibility == FolderVisibility.PUBLIC

    @property
    def is_private(self) -> bool:
        """是否为私有文件夹"""
        return self.visibility == FolderVisibility.PRIVATE

    @property
    def full_path(self) -> str:
        """获取完整路径"""
        return self.path

    @property
    def path_components(self) -> list:
        """获取路径组件列表"""
        if not self.path:
            return []
        return [comp for comp in self.path.split('/') if comp]

    @property
    def depth(self) -> int:
        """获取层级深度"""
        return len(self.path_components)

    @property
    def can_delete(self) -> bool:
        """检查是否可以删除"""
        return not self.is_system and not self.is_locked and not self.is_deleted

    @property
    def can_rename(self) -> bool:
        """检查是否可以重命名"""
        return not self.is_system and not self.is_locked

    def build_path(self, parent_path: str = "") -> str:
        """构建路径"""
        if parent_path:
            return f"{parent_path}/{self.name}"
        return self.name

    def update_path(self, new_path: str) -> None:
        """更新路径"""
        self.path = new_path
        self.level = self.depth

    def get_ancestors(self) -> list:
        """获取所有祖先文件夹"""
        ancestors = []
        current = self.parent
        while current:
            ancestors.append(current)
            current = current.parent
        return ancestors

    def get_descendants(self, include_self: bool = False) -> list:
        """获取所有后代文件夹"""
        descendants = []
        if include_self:
            descendants.append(self)
        
        for child in self.children:
            descendants.append(child)
            descendants.extend(child.get_descendants())
        
        return descendants

    def update_content_count(self, increment: int = 1) -> None:
        """更新内容数量"""
        self.content_count += increment
        
        # 递归更新父文件夹
        if self.parent:
            self.parent.update_total_content_count(increment)

    def update_total_content_count(self, increment: int = 1) -> None:
        """更新总内容数量（包括子文件夹）"""
        self.total_content_count += increment
        
        # 递归更新父文件夹
        if self.parent:
            self.parent.update_total_content_count(increment)

    def update_subfolder_count(self, increment: int = 1) -> None:
        """更新子文件夹数量"""
        self.subfolder_count += increment

    def mark_as_archived(self) -> None:
        """标记为已归档"""
        self.is_archived = True
        self.archived_at = func.now()
        
        # 递归归档子文件夹
        for child in self.children:
            if not child.is_archived:
                child.mark_as_archived()

    def mark_as_deleted(self) -> None:
        """标记为已删除"""
        self.is_deleted = True
        self.deleted_at = func.now()
        
        # 递归删除子文件夹
        for child in self.children:
            if not child.is_deleted:
                child.mark_as_deleted()

    def restore(self) -> None:
        """恢复文件夹"""
        self.is_deleted = False
        self.deleted_at = None
        
        # 如果父文件夹也被删除，则递归恢复
        if self.parent and self.parent.is_deleted:
            self.parent.restore()

    def mark_as_accessed(self) -> None:
        """标记为已访问"""
        self.last_accessed_at = func.now()

    def validate_name(self, new_name: str) -> bool:
        """验证文件夹名称"""
        if not new_name or len(new_name.strip()) == 0:
            return False
        
        # 检查是否包含非法字符
        invalid_chars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|']
        if any(char in new_name for char in invalid_chars):
            return False
        
        # 检查长度
        if len(new_name) > 100:
            return False
        
        return True

    def rename(self, new_name: str) -> bool:
        """重命名文件夹"""
        if not self.validate_name(new_name):
            return False
        
        if not self.can_rename:
            return False
        
        old_name = self.name
        self.name = new_name.strip()
        
        # 更新路径
        if self.parent:
            parent_path = self.parent.path
            self.path = self.build_path(parent_path)
        else:
            self.path = new_name.strip()
        
        # 递归更新子文件夹路径
        self._update_children_paths()
        
        return True

    def _update_children_paths(self) -> None:
        """递归更新子文件夹路径"""
        for child in self.children:
            child.path = child.build_path(self.path)
            child._update_children_paths()

    def get_breadcrumb(self) -> list:
        """获取面包屑导航"""
        breadcrumb = []
        current = self
        while current:
            breadcrumb.append({
                "id": current.id,
                "name": current.name,
                "path": current.path
            })
            current = current.parent
        
        return list(reversed(breadcrumb))

    def to_dict(self, include_children: bool = False) -> dict:
        """转换为字典"""
        data = {
            "id": str(self.id),
            "name": self.name,
            "description": self.description,
            "path": self.path,
            "level": self.level,
            "folder_type": self.folder_type,
            "visibility": self.visibility,
            "color": self.color,
            "icon": self.icon,
            "content_count": self.content_count,
            "total_content_count": self.total_content_count,
            "subfolder_count": self.subfolder_count,
            "is_system": self.is_system,
            "is_locked": self.is_locked,
            "is_archived": self.is_archived,
            "is_deleted": self.is_deleted,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "updated_at": self.updated_at.isoformat() if self.updated_at else None,
        }
        
        if include_children and self.children:
            data["children"] = [child.to_dict(include_children=True) for child in self.children]
        
        return data